home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9207.ZIP / FILTER.ASC < prev    next >
Text File  |  1992-06-15  |  20KB  |  462 lines

  1. _GRAPHICS IMPORT FILTERS FOR WINDOWS APPLICATIONS_
  2. by Evangelo Prodromou
  3.  
  4. [LISTING ONE]
  5.  
  6. /****************************************************************************
  7.     FILE   : Viewer.h
  8.     PURPOSE: header file for graphic viewer
  9.     (C) 1992, Evangelo Prodromou.  All rights reserved.
  10. ****************************************************************************/
  11.  
  12. /* Viewer Menu item definitions */
  13. #define IDM_ABOUT       100
  14. #define IDC_STATIC      -1
  15.  
  16. /*  general-use string size. */
  17. #define STRINGSIZE 511
  18.  
  19. /* The following definitions are data types defined by the Aldus Interface. */
  20. typedef DWORD FILETYPE;
  21. typedef struct {
  22.    unsigned    slippery : 1;        /* TRUE if file may disappear. */
  23.    unsigned    write : 1;           /* TRUE if open for write. */
  24.    unsigned    unnamed : 1;         /* TRUE if unnamed. */
  25.    unsigned    linked : 1;          /* Linked to an FS FCB. */
  26.    unsigned    mark : 1;            /* Generic mark bit. */
  27.    FILETYPE    fType;               /* The file type. */
  28. #define IBMFNSIZE 124
  29.    short       handle;              /* MS-DOS open file handle. */
  30.    char        fullName[IBMFNSIZE]; /* Device, path, file names. */
  31.    DWORD       filePos;          /* Our current file posn. */
  32. } FILESPEC, FAR *LPFILESPEC;
  33.  
  34. typedef short DC;
  35. typedef struct {        /* --- PICTINFO for Windows --- */
  36.   HANDLE        hmf;    /* Global memory handle to the metafile */
  37.   RECT          bbox;   /* Tightly bounding rectangle in metafile units */
  38.   DC            inch;   /* Length of an inch in metafile units */
  39. } PICTINFO, FAR* LPPICTINFO;
  40.  
  41. /* The following types are pointers to functions with the same arguments
  42. ** as those found in an Aldus-standard function.  They are necessary to
  43. ** make anonymous function calls. */
  44.  
  45. /* Version 1.0 filter functions */
  46. typedef WORD (FAR PASCAL *PFN_INFO)   (short, LPSTR, HANDLE FAR*, HANDLE FAR*);
  47. typedef WORD (FAR PASCAL *PFN_IMPORT) (HDC, LPFILESPEC, LPPICTINFO, HANDLE);
  48. typedef void (FAR PASCAL *PFN_PREF)   (HANDLE, HWND, HANDLE, WORD);
  49.  
  50. /* Version 2.0 filter functions */
  51. typedef WORD (FAR PASCAL *PFN_VER)    (DWORD, BOOL FAR *, WORD FAR *, 
  52.                                                                    WORD FAR *);
  53. typedef WORD (FAR PASCAL *PFN_ISMY)   (LPFILESPEC);
  54. typedef WORD (FAR PASCAL *PFN_PREF2)  (HANDLE, HANDLE, HANDLE FAR *, DWORD, FARPROC, LPFILESPEC);
  55. typedef WORD (FAR PASCAL *PFN_OUTPUT) (HDC, HDC, LPFILESPEC, LPSTR, LPPICTINFO, HANDLE, FARPROC, BOOL);
  56.  
  57. /* Function declarations for functions local to this application. */
  58. int PASCAL WinMain( HANDLE, HANDLE, LPSTR, int );
  59. long FAR PASCAL MainWndProc( HWND, unsigned, WORD, LONG );
  60. BOOL FAR PASCAL AboutDlgProc( HWND, unsigned, WORD, LONG );
  61. BOOL NEAR ImportFile( HWND );
  62. BOOL NEAR GetExtFilter( void );
  63. HDC NEAR GetPrinterIC( void );
  64.  
  65.  
  66. [LISTING TWO]
  67.  
  68. /****************************************************************************
  69.     FILE   : Viewer.c
  70.     PURPOSE: Graphics file viewer
  71.     FUNCTIONS:
  72.     WinMain() - calls initialization function, processes message loop
  73.     MainWndProc() - processes messages
  74.     ImportFile() - Converts graphics file to Windows Metafile
  75.     GetExtFilter() - Determines correct filter for chosen file
  76.     GetPrinterIC() - Determines current printer
  77.     AboutDlgProc() - processes messages for "About" dialog box
  78.     COMMENTS:
  79.     (C) 1992, Evangelo Prodromou.  All rights reserved.
  80. ****************************************************************************/
  81.  
  82. /* include the general Windows header and the header for this application. */
  83. #include "windows.h"                
  84. #include "viewer.h"
  85.  
  86. /* These strings are used repeatedly. */
  87. char    szAppName[ ]            = "GraphicViewer";        
  88. char    szClassName[ ]          = "ViewerWClass";
  89. char    szMenuName[ ]           = "ViewerMenu";
  90.  
  91. char    szString[ STRINGSIZE ];          /* General use string. */
  92. char    szFilter[ IBMFNSIZE ];  /* full path name of import filter. */
  93.  
  94. /* Info struct of the imported metafile. */
  95. PICTINFO PictInfo = { NULL,0,0,0,0,0 };
  96.  
  97. /* Spec struct for file to import. */
  98. FILESPEC FileSpec = { 0,0,0,0,0,0L,NULL };
  99. HANDLE  hInst;                    /* Handle for this instance. */
  100.  
  101. /***************************************************************************
  102. FUNCTION: WinMain
  103. PURPOSE:  Entrance point of application
  104. ARGS:     hInstance     : handle to this instance.
  105.       hPrevInstance : handle to previous instance of the application.
  106.       lpCmdLine     : command line string
  107.       nCmdShow      : show full or iconic? Passed to ShowWindow()
  108. COMMENTS: If no previous instance, registers the window class.
  109.       Saves this instance handle as a global variable.  
  110.       Parses command line for a file name to view.  
  111.       Creates window for this instance. 
  112.       Shows the window.
  113.       Takes and translates messages from the message loop and passes
  114.          them on to MainWndProc().
  115. ***************************************************************************/
  116. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  117. {
  118.     MSG             msg;    /* Windows message structure */
  119.     WNDCLASS        wc;     /* Window class structure. */
  120.     HWND            hMain;  /* handle to main window.  */
  121. /* If there is no previous instance of the application, fill in the 
  122. ** window class structure and register the class. */
  123.     if (!hPrevInstance)
  124.     {       
  125.         wc.style =              NULL;                    
  126.         wc.lpfnWndProc =        MainWndProc;       
  127.         wc.cbClsExtra =         0;                  
  128.         wc.cbWndExtra =         0;                  
  129.         wc.hInstance =          hInstance;           
  130.         wc.hIcon =              LoadIcon(NULL, IDI_APPLICATION);
  131.         wc.hCursor =            LoadCursor(NULL, IDC_ARROW);
  132.         wc.hbrBackground =      GetStockObject(WHITE_BRUSH); 
  133.         wc.lpszMenuName =       (LPSTR) szMenuName;   
  134.         wc.lpszClassName =      (LPSTR) szClassName; 
  135.         if (!RegisterClass(&wc))
  136.             return FALSE;
  137.     }       
  138. /* Save the instance handle as a global variable. */
  139.     hInst = hInstance;
  140. /* Copy the command line argument to the filename field of FileSpec. */
  141.     lstrcpy( FileSpec.fullName,  lpCmdLine );
  142. /* Create the main window (will send WM_CREATE to the MainWndProc). */
  143.     hMain = CreateWindow( szClassName, szAppName,         
  144.             WS_OVERLAPPEDWINDOW,            
  145.             CW_USEDEFAULT, CW_USEDEFAULT,                  
  146.             CW_USEDEFAULT, CW_USEDEFAULT,                  
  147.             NULL, NULL, hInstance, NULL );
  148.     if (!hMain)
  149.         return (FALSE);
  150. /* Show the window and update it ( sends WM_PAINT to MainWndProc ). */
  151.     ShowWindow(hMain, nCmdShow);  
  152.     UpdateWindow(hMain);
  153. /* Get window messages for this instance and send them to the MainWndProc. 
  154. ** Loops until WM_QUIT message is received. */
  155.     while ( GetMessage( &msg,NULL,NULL,NULL )  )            
  156.     {
  157.         TranslateMessage( &msg );    
  158.         DispatchMessage( &msg );     
  159.     }
  160.     return ( msg.wParam );       
  161. }
  162. /***************************************************************************
  163. FUNCTION: MainWndProc
  164. PURPOSE:  Processes messages for main window
  165. ARGS:     hWnd          : handle to main window
  166.       message       : windows message
  167.       wParam        : extra message info
  168.       lParam        : extra message info
  169. MESSAGES: WM_CREATE     : If a file was specified on the command line, gets
  170.               the correct filter by extension, and tries to
  171.               import it.  If no file specified, or if no matching
  172.               filter is found, asks for a new file.
  173.       WM_PAINT      : If a file has been imported, displays the 
  174.               resulting metafile.  Otherwise, passes the message
  175.               to default.
  176.       WM_SIZE       : Invalidate whole client area, and repaint.
  177.       WM_DESTROY    : Terminates program.
  178.       WM_COMMAND    : IDM_ABOUT     : Displays About dialog box.
  179. ***************************************************************************/
  180. long FAR PASCAL MainWndProc(HWND hWnd, unsigned message, WORD wParam, LONG lParam)
  181. {
  182.     FARPROC lpProc;               
  183.     BOOL    bError;
  184.     RECT        rc;
  185.     switch (message) 
  186.     {
  187.     case WM_CREATE:
  188.       /* Assume an error to begin with. */
  189.       bError = TRUE;
  190.       if ( FileSpec.fullName[0] == '\0' ) /* No filename on command line */
  191.         {
  192.         lstrcpy( (LPSTR) szString, "No file name specified." );
  193.         }
  194.         else if ( !GetExtFilter( ) ) /* Unable to find filter */
  195.         {
  196.         lstrcpy( (LPSTR) szString, 
  197.             "No filter specified in WIN.INI for file extension." );
  198.         }
  199.         else if ( !ImportFile( hWnd ) ) /* Unable to import */
  200.         {
  201.         lstrcpy( (LPSTR) szString, "Unable to import file." );
  202.         }   
  203.         else bError = FALSE;  /* Import was a success */
  204.         if (bError) 
  205.         {
  206.         MessageBox( hWnd, (LPSTR) szString, 
  207.                      (LPSTR) szAppName, MB_OK | MB_ICONHAND );
  208.         DestroyWindow( hWnd );
  209.         }
  210.         break;
  211.     case WM_PAINT:     /* Paint window by playing metafile. */
  212.         if ( PictInfo.hmf ) /* A file has been imported. */
  213.          {  
  214.         PAINTSTRUCT     ps;
  215.         HDC             hDC = BeginPaint( hWnd, &ps );
  216.         SetMapMode( hDC, MM_ANISOTROPIC );
  217.         SetWindowExt( hDC, PictInfo.bbox.right - PictInfo.bbox.left,
  218.                         PictInfo.bbox.bottom - PictInfo.bbox.top );
  219.          GetClientRect( hWnd, &rc );
  220.          SetViewportExt( hDC, rc.right - rc.left, rc.bottom - rc.top );
  221.          SetWindowOrg( hDC, PictInfo.bbox.left, PictInfo.bbox.top );
  222.          PlayMetaFile( hDC, PictInfo.hmf );
  223.          EndPaint( hWnd, &ps );
  224.            }
  225.            break;
  226.     case WM_SIZE:  /* Invalidate, and paint full window. */
  227.         GetClientRect( hWnd, &rc );
  228.         InvalidateRect( hWnd, &rc, TRUE);
  229.         UpdateWindow( hWnd );
  230.         break;
  231.     case WM_DESTROY:  /* Send WM_QUIT message to message loop to end. */
  232.         PostQuitMessage( hWnd );
  233.         break;
  234.     case WM_COMMAND:  /* Creates About dialog box. */
  235.         if ( wParam == IDM_ABOUT )
  236.         {
  237.             lpProc = MakeProcInstance( AboutDlgProc, hInst );
  238.             DialogBox( hInst, "AboutBox", hWnd, lpProc );
  239.             FreeProcInstance( lpProc );
  240.             break;
  241.         }  /* Otherwise, fall through to default. */
  242.     default:
  243.         return ( DefWindowProc( hWnd, message, wParam, lParam ) );
  244.     }
  245.     return (NULL);
  246. }
  247. /***************************************************************************
  248. *       FUNCTION: ImportFile                                               *
  249. *       PURPOSE : Translate a graphic file to a metafile using a filter    *
  250. *       ARGS    : HWND hWnd - handle to main window.                       *
  251. *       RETURN  : TRUE if file import is successful, otherwise FALSE.      *
  252. *       COMMENTS: Loads a filter DLL into memory, and uses it's import     *
  253. *                 functionality to translate a graphic file to a metafile. *
  254. *                 Uses Aldus-standard interface functions, version 1 or 2. *
  255. ***************************************************************************/
  256. BOOL NEAR ImportFile(HWND hWnd)
  257. {
  258.     HANDLE          hFilter = NULL, hPrefMem = NULL;
  259.     WORD            wFilterResult = -1;
  260.     HDC             hPrintIC = NULL;
  261. /* Version 1.0 Filter functions */
  262.     PFN_INFO        lpfnGetFilterInfo = NULL;
  263.     PFN_IMPORT      lpfnImportGR = NULL;
  264.     PFN_PREF        lpfnGetFilterPref = NULL;
  265. /* Version 2.0 Filter functions */
  266.     PFN_VER         lpfnGetFilterVersion = NULL;
  267.     PFN_ISMY        lpfnIsThisMyFile = NULL;
  268.     PFN_PREF2       lpfnGetFilterPref2 = NULL;
  269.     PFN_OUTPUT      lpfnOutputGR = NULL;
  270. /* Load appropriate filter. */
  271.     hFilter = LoadLibrary( (LPSTR) szFilter );
  272. /* Try to find "GetFilterVersion." */
  273.     lpfnGetFilterVersion = GetProcAddress( hFilter, "GetFilterVersion" );
  274.     if ( !lpfnGetFilterVersion ) /* This is a v 1.0 filter. */
  275.     {
  276.         lpfnGetFilterInfo = GetProcAddress( hFilter, "GetFilterInfo" );
  277.         if ( lpfnGetFilterInfo )
  278.         {
  279.         wFilterResult=(*lpfnGetFilterInfo)( 2, NULL, &hPrefMem, NULL );
  280.         } 
  281. /* Call filter's GetFilterPref function, which creates a "filter preference"
  282. ** dialog box to set import options. */
  283.         lpfnGetFilterPref = GetProcAddress( hFilter, "GetFilterPref" );
  284.         if ( lpfnGetFilterPref )
  285.         {   
  286.             (*lpfnGetFilterPref)( hInst, hWnd, hPrefMem, 1 );
  287.         }
  288. /* Call filter's ImportGR function to convert the file to a Windows
  289. ** metafile (information is stored in FileSpec). */
  290.         lpfnImportGR = GetProcAddress( hFilter, "ImportGR" );
  291.         if ( lpfnImportGR )
  292.         {
  293.             hPrintIC = GetPrinterIC();
  294.             wFilterResult = (*lpfnImportGR)( hPrintIC, &FileSpec, &PictInfo, hPrefMem );
  295.         }
  296.     }
  297.     else /* This is a v. 2.0 or higher filter. */
  298.     {
  299. /* Ensure that current file is compatible with current filter. */
  300.         lpfnIsThisMyFile = GetProcAddress( hFilter, "IsThisMyFile" );
  301.         if ( lpfnIsThisMyFile )
  302.         {
  303.             (*lpfnIsThisMyFile) ( &FileSpec );
  304.         }
  305. /* Get user's import preferences. */
  306.            lpfnGetFilterPref2 = GetProcAddress( hFilter, "GetFilterPref" );
  307.            if (lpfnGetFilterPref2)
  308.         {
  309.          wFilterResult = (*lpfnGetFilterPref2) ( hInst, hWnd, &hPrefMem, FileSpec.fType, NULL, &FileSpec);
  310.         }
  311. /* Convert chosen file to a metafile. */
  312.         lpfnOutputGR = GetProcAddress( hFilter, "OutputGR" );
  313.         if (lpfnOutputGR)
  314.         {
  315.             hPrintIC = GetPrinterIC();
  316.             wFilterResult = (*lpfnOutputGR) ( NULL, hPrintIC,
  317.                 &FileSpec, NULL, &PictInfo, hPrefMem, NULL, FALSE);
  318.         }
  319.     }
  320. /* Free the memory allocated to the filter DLL and the preference memory.*/
  321.     FreeLibrary( hFilter );
  322.     GlobalFree( hPrefMem );
  323. /* Set the window title to the file name, or return false. */
  324.     if ( wFilterResult == 0 ) 
  325.     {
  326.         SetWindowText( hWnd, FileSpec.fullName );
  327.         return TRUE;
  328.     }
  329.     else
  330.     {
  331.         return FALSE;
  332.     }
  333. }
  334. /***************************************************************************
  335. *       FUNCTION: GetExtFilter                                             *
  336. *       PURPOSE : Get filename of filter appropriate for current file.     *
  337. *       ARGS    : none                                                     *
  338. *       RETURN  : TRUE if able to find filter, otherwise FALSE.            *
  339. *       COMMENTS: Gets all filter names listed under [GraphicViewer]       *
  340. *                 heading in WIN.INI.  Checks which one entry supports     *
  341. *                 files with the same extension as FileSpec.fullName.      *
  342. ***************************************************************************/
  343. BOOL NEAR GetExtFilter( void )
  344. {
  345.     PSTR pDesc, pExt, pSupExt;
  346.     int  nLen = lstrlen( FileSpec.fullName );
  347.     /* Set pExt to last char in FileSpec.fullName. */
  348.     if (!nLen) return FALSE;
  349.     pExt = FileSpec.fullName + nLen - 1; 
  350.     /* decrement to character after period ('.'). */
  351.     while ( *(pExt-1) != '.' )  
  352.     {
  353.         pExt--;
  354.         if ( pExt == FileSpec.fullName ) return FALSE;
  355.     }
  356.     /* get all profile string entries (description of filter). */
  357.     nLen = GetProfileString( szAppName, NULL, NULL, szString, STRINGSIZE );
  358.     /* start with the first description. */
  359.     pDesc = szString;
  360.     /* while we still have a string to check... */
  361.     while ( pDesc < szString + nLen )
  362.     {
  363.         /* get the entry for this filter
  364.         ("[filter file name],[ext]") */
  365.         GetProfileString( (LPSTR) szAppName, (LPSTR) pDesc, 
  366.                   NULL, (LPSTR) szFilter, IBMFNSIZE );
  367.        /* if one exists, and its extension matches the file extension... */
  368.         pSupExt = szFilter + lstrlen( (LPSTR) szFilter) - 1;
  369.         while ( *( pSupExt - 1 ) != ',' )
  370.         {
  371.             pSupExt--;
  372.             if (pSupExt == szFilter) return FALSE;
  373.         }
  374.         if( lstrcmpi( (LPSTR) pExt, (LPSTR) pSupExt ) == 0 )
  375.         {
  376.             *(pSupExt-1) = '\0'; 
  377.             return TRUE;
  378.         }
  379.         else
  380.         {
  381.                /* move on to next filter. */
  382.                pDesc += lstrlen( (LPSTR) pDesc ) + 1;
  383.         }
  384.     }
  385.     /* if we get here, we couldn't find one. Make sure szFilter is blank.*/
  386.     szFilter[0] = '\0';
  387.     /* Report failure. */
  388.     return FALSE;
  389. }
  390. /***************************************************************************
  391. *       FUNCTION: GetPrinterIC                                             *
  392. *       PURPOSE : Get information context for active print device.         *
  393. *       ARGS    : none                                                     *
  394. *       RETURN  : handle to printer's information context or NULL if fail. *
  395. *       COMMENTS: Gets device description from [windows] heading in        *
  396. *                 WIN.INI.  Breaks down the description into device name,  *
  397. *                 driver name, and output port.  Uses CreateIC() to get    *
  398. *                 an information context.                                  *
  399. ***************************************************************************/
  400. HDC GetPrinterIC( void )
  401. {
  402.     int  nLen;
  403.     PSTR pDevice, pDriver, pOutput;
  404.     HDC  hPrintIC = NULL;
  405. /* Get the information on the current printer, listed under "windows" in
  406. ** WIN.INI as "device=[device name],[driver],[output port]". */
  407.     nLen = GetProfileString("windows", "device", NULL,(LPSTR) szString, STRINGSIZE);
  408. /* Break it down into device name, driver name, output port. */
  409.     if ( nLen )
  410.     {
  411.     /* The device name is the beginning of the string. */
  412.         pDevice = szString;
  413.     /* The driver name comes right after the first comma ','. */
  414.         pDriver = szString;
  415.         while ( ( *pDriver != ',' ) )
  416.         {
  417.              pDriver++;
  418.              if ( pDriver >= szString + nLen ) return NULL;
  419.         }        
  420.         *pDriver = '\0';        pDriver++;
  421.     /* The output port name comes right after the second comma ','. */
  422.         pOutput = pDriver;
  423.         while ( ( *pOutput != ',' ) )
  424.         {
  425.              pOutput++;
  426.              if ( pOutput >= szString + nLen ) return NULL;
  427.         }        
  428.         *pOutput = '\0';        pOutput++;
  429.     /* Create an information context for this device. */
  430.         hPrintIC = CreateIC( (LPSTR) pDriver, (LPSTR) pDevice,
  431.                     (LPSTR) pOutput, NULL );
  432.     }
  433.     return ( hPrintIC ); 
  434. }
  435. /***************************************************************************
  436. *       FUNCTION: AboutDlgProc                                             *
  437. *       PURPOSE : Handles messages for AboutBox dialog box.                *
  438. *       ARGS    : Standard callback arguments.                             *
  439. *       RETURN  : N/A.                                                     *
  440. *       COMMENTS: Closes AboutBox when OK button, Enter or ESC are pressed.*
  441. ***************************************************************************/
  442. BOOL FAR PASCAL AboutDlgProc(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  443. {
  444.     switch (message) 
  445.     {
  446.     case WM_INITDIALOG:  /* Beginning. No functionality. */              
  447.         return (TRUE);
  448.     case WM_COMMAND:
  449.         switch (wParam)
  450.         {
  451.             case IDOK:  /* OK or Enter were pressed. */              
  452.             case IDCANCEL: /* Esc was pressed. */
  453.                 EndDialog(hDlg, TRUE);        
  454.                 return (TRUE);
  455.         }
  456.         break;
  457.     }
  458.     return (FALSE);                           
  459. }
  460.  
  461.  
  462.